import { FormItemComponent } from './../form/form-item.component';
import { Component, AfterViewInit, ElementRef, OnInit, EventEmitter, TemplateRef, Input, ContentChild, ViewChild, Output } from '@angular/core';
import { SafeStyle, DomSanitizer } from '@angular/platform-browser';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { ElementuiService } from './../elementui.service';

@Component({
  selector: 'el-input',
  templateUrl: './input.component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: InputComponent,
    multi: true
  }],
})


export class InputComponent implements OnInit, AfterViewInit, ControlValueAccessor {
  private sanitizer: any;
  private el: any;
  private form: any;
  private controlChange: any;
  private controlTouch: any;

  @ContentChild('prepend')
  prepend!: TemplateRef<any>;
  @ContentChild('append')
  append!: TemplateRef<any>;
  @ViewChild('textarea') textarea: any;
  @ContentChild('suffix') suffix!: TemplateRef<any>;
  @ContentChild('prefix') prefix!: TemplateRef<any>;
  textareaStyles: SafeStyle = '';
  @Input() autosize: any;
  @Input() type: string = 'text';
  @Input() value: string | number = '';
  @Input() maxlength: number = 0;
  @Input() minlength: number = 0;
  @Input() placeholder: string = '';
  @Input() size: string = '';
  @Input() rows: number = 0;
  @Input() resize: string = '';
  @Input() icon: string = '';
  @Input('icon-class') iconClass: string = '';
  @Input('auto-complete') autoComplete: string = '';
  @Input() name: string = '';
  @Input('native-type') nativeType: string = 'text';
  @Input() readonly: boolean = false;
  @Input('prefix-icon') prefixIcon: string = '';
  @Input('suffix-icon') suffixIcon: string = '';
  @Input() autofocus: boolean = false;
  @Input() clearable: boolean = false;
  @Input('show-password') showPassword: boolean = false;
  @Input('show-word-limit') showWordLimit: boolean = false;
  @Input('parent-class') parentClass: string = ' ';

  passwordVisible: boolean = false;
  @Input() model: any;
  @Output('change') modelChange: EventEmitter<any> = new EventEmitter();
  @Output('clear') modelClear: EventEmitter<any> = new EventEmitter();
  @Output('icon-click') iconClick: EventEmitter<any> = new EventEmitter();
  @Output('focus') focus: EventEmitter<any> = new EventEmitter();
  @Output('blur') blur: EventEmitter<any> = new EventEmitter();
  @Output('icon-mouseEnter') iconMouseEnter: EventEmitter<any> = new EventEmitter();
  @Output('icon-mouse-leave') iconMouseLeave: EventEmitter<any> = new EventEmitter();
  @Output('icon-mousedown') iconMousedown: EventEmitter<any> = new EventEmitter();
  @Output('icon-mouseup') iconMouseup: EventEmitter<any> = new EventEmitter();
  @Input() disabled: boolean = false;
  hovering: boolean = false;

  CONTEXT_STYLE: Array<string> = [
    'letter-spacing',
    'line-height',
    'padding-top',
    'padding-bottom',
    'font-family',
    'font-weight',
    'font-size',
    'text-rendering',
    'text-transform',
    'width',
    'text-indent',
    'padding-left',
    'padding-right',
    'border-width',
    'box-sizing',
  ];

  constructor(sanitizer: DomSanitizer, el: ElementRef, form: FormItemComponent, private ElementuiService: ElementuiService) {
    this.sanitizer = sanitizer;
    this.el = el;
    this.form = form;
    this.controlChange = function () { };
    this.controlTouch = function () { };
  };

  typeClass() {
    return (this.type === 'textarea') ? ' el-textarea' : ' el-input';
  }

  sizeClass() {
    return this.size ? ' el-input--' + this.size : '';
  }
  disabledClass() {
    return this.disabled ? ' is-disabled' : '';
  }
  appendClass() {
    return this.append ? ' el-input-group el-input-group--append' : '';
  }
  prependClass() {
    return this.prepend ? ' el-input-group el-input-group--prepend' : '';
  }
  prefixClass() {
    return (this.prefix || this.prefixIcon) ? ' el-input--prefix' : '';
  }

  suffixClass() {
    return (this.suffix || this.suffixIcon || this.clearable || this.showPassword) ? ' el-input--suffix' : '';
  }

  getSuffixVisible() {
    return (this.suffix || this.suffixIcon || this.clearable || this.showPassword || this.isWordLimitVisible()) ? true : false;
  }

  getSuffixTmpVisible() {
    return (this.showClear() || this.showPwdVisible() || this.isWordLimitVisible()) ? false : true;
  }

  makeTextareaStyles() {
    if (!this.autosize || this.type !== 'textarea')
      return;
    var /** @type {?} */ height = this.getTextareaHeight(this.textarea.nativeElement, this.autosize.minRows, this.autosize.maxRows);
    var /** @type {?} */ styles = "resize: " + this.resize + "; height: " + height + ";";
    this.textareaStyles = this.sanitizer.bypassSecurityTrustStyle(styles);
  }

  handleInput(val: any) {

    this.model = val;
    this.modelChange.emit(val);
    this.controlChange(val);

  }

  handleBlur(event:Event){
    var val = (event.target as any).value;
    this.blur.emit(val);
  }

  handleFocus(event:Event){
    var val = (event.target as any).value;
    this.focus.emit(val);
  }


  handleTextarea(event: Event) {
    var val: any = (event.target as any).value;
    var _this = this;
    this.model = val;
    this.modelChange.emit(val);
    this.controlChange(val);
    var /** @type {?} */ timer = setTimeout(function () {
      _this.makeTextareaStyles();
      clearTimeout(timer);
    }, 0);
  }

  clear(event: any) {
    var val = '';
    this.model = val;
    this.modelChange.emit(val);
    this.modelClear.emit(val);
    this.controlChange(val);
  }

  handlePasswordVisible(event: any) {
    this.passwordVisible = !this.passwordVisible;
    this.type = (this.passwordVisible === true) ? 'password' : 'text';
    this.focus.emit()
  }

  getNativeType() {
    this.passwordVisible = this.type === 'password' ? true : false;
    return this.type;
  }

  showPointer() {
    var /** @type {?} */ clickEvent = !!(this.iconClick.observers && this.iconClick.observers.length);
    var /** @type {?} */ mouseEvent = !!(this.iconMousedown.observers && this.iconMousedown.observers.length);
    return clickEvent || mouseEvent;
  }

  isWordLimitVisible() {
    return this.showWordLimit &&
      this.maxlength &&
      (this.type === 'text' || this.type === 'textarea') &&
      !this.disabled &&
      !this.readonly &&
      !this.showPassword;
  }
  showPwdVisible() {
    return this.showPassword &&
      !this.disabled &&
      !this.readonly && (this.model && String(this.model).length > 0);
  }
  showClear() {
    return this.clearable  && (this.model && String(this.model).length > 0);
  }


  writeValue(obj: any): void {
    this.model = obj;
  }
  registerOnChange(fn: any): void {
    this.controlChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.controlTouch = fn;
  }

  ngAfterViewInit() {
    var _this = this;
    // no content required
    if (this.type === 'textarea') {
       setTimeout(function () {
          _this.makeTextareaStyles();
      }, 0);
    }
    return;
  }

  ngOnInit(): void {
    var _this = this;


    // auto follow form status
    var /** @type {?} */ parentIsForm = this.ElementuiService.isParentTag(this.el.nativeElement, 'el-form-item');
    if (parentIsForm) {
      var /** @type {?} */ iconStatus_1: any = {
        error: 'circle-close', success: 'circle-check', validating: 'circle-validating',
      };
      this.iconClass = 'el-input__validateIcon';
      this.form.statusSubscriber.push(function (status: any) {
        _this.icon = iconStatus_1[status] || '';
      });
    }
    if (this.value && !this.model) {
      this.model = this.value;
    }
    
  }

  textLength() {
    return String(this.value).length;
  }

  getTextareaHeight(targetElement: any, minRows: any, maxRows: any) {
    var /** @type {?} */ hiddenTextarea;
    var /** @type {?} */ HIDDEN_STYLE = "\n  height:0 !important;\n  visibility:hidden !important;\n  overflow:hidden !important;\n  position:absolute !important;\n  z-index:-1000 !important;\n  top:0 !important;\n  right:0 !important;\n";

    if (minRows === void 0) { minRows = null; }
    if (maxRows === void 0) { maxRows = null; }
    if (!hiddenTextarea) {
      hiddenTextarea = document.createElement('textarea');
      document.body.appendChild(hiddenTextarea);
    }
    var _a = this.calculateNodeStyling(targetElement);
    var paddingSize = _a.paddingSize, borderSize = _a.borderSize, boxSizing = _a.boxSizing, contextStyle = _a.contextStyle;
    hiddenTextarea.setAttribute('style', contextStyle + ";" + HIDDEN_STYLE);
    hiddenTextarea.value = targetElement.value || targetElement.placeholder || '';
    var /** @type {?} */ height = hiddenTextarea.scrollHeight;
    if (boxSizing === 'border-box') {
      height += borderSize;
    }
    else if (boxSizing === 'content-box') {
      height -= paddingSize;
    }
    hiddenTextarea.value = '';
    var /** @type {?} */ singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
    if (minRows !== null) {
      var /** @type {?} */ minHeight = singleRowHeight * minRows;
      if (boxSizing === 'border-box') {
        minHeight += paddingSize + borderSize;
      }
      height = Math.max(minHeight, height);
    }
    if (maxRows !== null) {
      var /** @type {?} */ maxHeight = singleRowHeight * maxRows;
      if (boxSizing === 'border-box') {
        maxHeight += paddingSize + borderSize;
      }
      height = Math.min(maxHeight, height);
    }
    return height + 'px';
  }

  calculateNodeStyling(targetElement: any) {
    var /** @type {?} */ style = window.getComputedStyle(targetElement);
    var /** @type {?} */ boxSizing = style.getPropertyValue('box-sizing');
    var /** @type {?} */ paddingSize = (parseFloat(style.getPropertyValue('padding-bottom')) +
      parseFloat(style.getPropertyValue('padding-top')));
    var /** @type {?} */ borderSize = (parseFloat(style.getPropertyValue('border-bottom-width')) +
      parseFloat(style.getPropertyValue('border-top-width')));
    var /** @type {?} */ contextStyle = this.CONTEXT_STYLE
      .map(function (name: any) { return name + ":" + style.getPropertyValue(name); })
      .join(';');
    return { contextStyle: contextStyle, paddingSize: paddingSize, borderSize: borderSize, boxSizing: boxSizing };
  }

}
